home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 722 / 722.xpi / chrome / noscript.jar / content / noscript / AddressMatcher.js < prev    next >
Text File  |  2010-02-12  |  6KB  |  231 lines

  1. function AddressMatcher(s) {
  2.   this.source = s;
  3.   this.rx = this.parse(s);
  4. }
  5. AddressMatcher.create = function(s) {
  6.   return s && new AddressMatcher(s);
  7. }
  8.  
  9. AddressMatcher.prototype = {
  10.   rx: null,
  11.   networks: null,
  12.   netMatching: false,
  13.   
  14.   test: function(u) {
  15.     return this.rx && this.rx.test(u);  
  16.   },
  17.   
  18.   testURI: function(uri) {
  19.     return this.test(uri.spec);  
  20.   },
  21.   
  22.   _networkTest: function(uri, canDoDNS, allIPs) {
  23.     var res = this.rx && this.rx.test(uri.spec || uri);
  24.     if (res || !canDoDNS) return res;
  25.     
  26.     if (!uri.spec) {
  27.       uri = IOS.newURI(uri, null, null);
  28.     }
  29.     try {
  30.       var host = uri.host
  31.       if (!host) return false;
  32.       if (Network.isNet(host))
  33.         return this._testIP(host);
  34.       
  35.       var dnsRecord = DNS.resolve(host);
  36.       if (dnsRecord && dnsRecord.valid) 
  37.         return allIPs ? dnsRecord.entries.every(this._testIP, this)
  38.                       : dnsRecord.entries.some(this._testIP, this);
  39.     } catch(e) {
  40.       dump(e + "\n");
  41.     }
  42.     return false;
  43.   },
  44.   
  45.   _testIP: function(ip) {
  46.      return this.networks.some(function(n) { return n.test(ip); });
  47.   },
  48.   
  49.   parse: function(s) {
  50.     try {
  51.       var rxSource = s && s.split(/\s+/).map(function(p) {
  52.         
  53.         if (p == '*') return '.*';
  54.         
  55.         if (!/\S+/.test(p)) return null;
  56.         
  57.         if (Network.isNet(p)) {
  58.           var net;
  59.           if (!this.netMatching) {
  60.             this.netMatching = true;
  61.             this.test = this.testURI = this._networkTest;
  62.             this.networks = [net = new Network(p)];
  63.           } else {
  64.             this.networks.push(net = new Network(p));
  65.           }
  66.           
  67.           if (p.indexOf("/") > -1 || (net.ipv4 ? net.mask < 32 : net.mask < 128))
  68.             return null; // is a whole network, using IP for URL doesn't make sense
  69.           
  70.           if (p.indexOf(":") > -1)
  71.             p = "[" + p + "]"; // prepare IPv6 URL host
  72.         }
  73.         
  74.         if(!/[^\w\-\[\]/:%@;&#\?\.\*]/.test(p)) {
  75.          
  76.           // either simple or glob
  77.           const hasPath = /^(?:\w+:\/\/|)[^\/]+\//.test(p);
  78.           const hasScheme = /^[a-z]\w+:(?:\/+|[^/]*\D)/.test(p);
  79.  
  80.           p = p.replace(/[\.\?\-]/g, "\\$&"); // escape special regexp chars
  81.  
  82.           if (!hasScheme) { // adjust for no protocol
  83.             p = "[a-z]+\\w+://" + p;
  84.           }
  85.  
  86.           if (!hasPath) { // adjust for no path
  87.             p += "(?:[/\\?#]|$)";
  88.           }
  89.           
  90.           if (!/\*/.test(p)) {
  91.             // simple "starts with..." site matching
  92.             return '^' + p;
  93.           }
  94.           
  95.           // glob matching
  96.           if (hasPath) p += '$'; 
  97.  
  98.           return '^' + p.replace(/\*/g, '.*?').replace(/^([^\/:]+:\/*)\.\*/, "$1[^/]*");
  99.         } 
  100.         // raw regexp!
  101.         try {
  102.          new RegExp(p); // check syntax
  103.         } catch(e) {
  104.           dump("Illegal regexp in AddressMatcher: " + p + " -- " + e + "\n");
  105.           return null;
  106.         }
  107.         return p;
  108.       }, this).filter(function(p) { return p; }).join("|");
  109.         
  110.       return rxSource ? new RegExp(rxSource) : null;
  111.     } catch(e) {
  112.       dump("Illegal AddressMatcher: " + s + " -- " + e + "\n");
  113.       return null;
  114.     }
  115.   }
  116. };
  117.  
  118. function Network(s) {
  119.   this.src = s;
  120.   var parts = s.split("/");
  121.   var addr = parts[0];
  122.   var smask;
  123.   
  124.   if (!this._isIPV4(addr))
  125.     this.ipv4 = false;
  126.   
  127.   if (parts.length > 1) {
  128.     this.mask = parseInt(parts[1]);
  129.     
  130.     var defMask = this.ipv4 ? 32 : 128;
  131.     
  132.     if (this.mask != defMask) {
  133.       if (this.mask > defMask) this.mask = defMask;
  134.       else {
  135.         if (this.ipv4) this.ipv4Mask = this._maskToBits(this.mask, 32)
  136.         else this.ipv6Mask = this._maskToBits(this.mask, 128);
  137.       }
  138.     }
  139.   } else if (!this.ipv4) {
  140.     this.mask = 128;
  141.   }
  142.   this.addr = this.ipv4 ? this._parseIPV4(addr) : this._parseIPV6(addr) ;
  143. }
  144.  
  145. Network.isNet = function(s) {
  146.   return /^(?:(?:\d+\.){1,3}\d*|[0-9af:]*:[0-9af:]*:[0-9af:]*)(:?\/\d{1,3})?$/i.test(s);
  147. }
  148.  
  149. Network.prototype = {
  150.   ipv4: true,
  151.   mask: 32,
  152.   ipv4Mask: 0xffffffff,
  153.   ipv6Mask: [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff],
  154.   
  155.   _isIPV4: function(addr) {
  156.     return addr.indexOf(":") < 0;
  157.   },
  158.   _maskToBits: function(mask, length) {
  159.     var smask = "", j = 0;
  160.     for(; j < mask; j++) smask += "1";
  161.     for(; j < length; j++) smask += "0";
  162.     if (length <= 32)
  163.       return parseInt(smask, 2);
  164.     var ret = [];
  165.  
  166.     for(j = 0; j < length; j += 32) {
  167.       ret.push(parseInt(smask.substring(j, j + 32), 2));
  168.     }
  169.     return ret;
  170.   },
  171.   
  172.   test: function(addr) {
  173.     addr = this.parse(addr);
  174.     if (typeof(addr) === "number")
  175.       return this.addr === addr;
  176.     
  177.     if (typeof(this.addr) === "number") return false;   
  178.     for (var j = this.addr.length; j-- > 0;) {
  179.       if (addr[j] !== this.addr[j]) return false;
  180.     }
  181.     return true;
  182.   },
  183.   
  184.   parse: function(addr) {
  185.     return this._isIPV4(addr) ? this._parseIPV4(addr) : this._parseIPV6(addr);
  186.   },
  187.   _parseIPV6: function(addr) {
  188.     var parts = addr.split(":");
  189.     var s = '', c, k, dz = false;
  190.     for (var j = 0, len = parts.length; j < len; j++) {
  191.       c = parts[j];
  192.       if (c.length === 0 && !dz) {
  193.         dz = true;
  194.         for (k = 9 - len; k-- >0;) s += "0000";
  195.       } else {
  196.         s += "0000".substring(c.length) + c;
  197.       }
  198.     }
  199.  
  200.     var ret = [0, 0, 0, 0];
  201.     var pos;
  202.     for (j = 4; j-- > 0; ) {
  203.       pos = j * 8;
  204.       ret[j] = parseInt(s.substring(pos, pos + 8), 16) & this.ipv6Mask[j];
  205.     }
  206.     return ret;
  207.   },
  208.   _pows: [0x1000000, 0x10000, 0x100, 1],
  209.   _parseIPV4: function(addr) {
  210.     var parts = addr.split(".");
  211.     var ret = 0, byt3;
  212.     for (var j = parts.length; j-- > 0;) {
  213.       byt3 = parseInt(parts[j]);
  214.       if (byt3) {
  215.         if (byt3 > 255) byt3 = 255;
  216.         ret += byt3 * this._pows[j];
  217.       } else if (j == parts.length - 1 && parts[j] == '') {
  218.         parts.pop();
  219.       }
  220.     }
  221.     if (parts.length < 4 && this.mask == 32 && typeof (this.addr) == "undefined") {
  222.       this.mask = parts.length * 8;
  223.       this.ipv4Mask = this._maskToBits(this.mask, 32);
  224.     }
  225.     return ret & this.ipv4Mask;
  226.   },
  227.   
  228.   toString: function() {
  229.     return this.src;
  230.   }
  231. };